package com.vcc.service.impl;

import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.vcc.core.util.DateUtil;
import com.vcc.core.util.RegexUtil;
import com.vcc.data.entity.Role;
import com.vcc.data.entity.TaskLogInfo;
import com.vcc.data.mapper.TaskLogInfoMapper;
import com.vcc.service.boss.response.taskLog.BossTaskLogInfoVo;
import com.vcc.service.client.vo.taskLog.TaskLogInfoVo;
import com.vcc.service.sa.BossUserUtil;
import com.vcc.service.service.TaskLogInfoService;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;

import static com.vcc.data.entity.table.BossUserTableDef.BOSS_USER;
import static com.vcc.data.entity.table.CardTypeTableDef.CARD_TYPE;
import static com.vcc.data.entity.table.TaskLogInfoTableDef.TASK_LOG_INFO;
import static com.vcc.data.entity.table.TaskLogTableDef.TASK_LOG;
import static com.vcc.data.entity.table.UserTableDef.USER;

@Service
public class TaskLogInfoServiceImpl extends ServiceImpl<TaskLogInfoMapper, TaskLogInfo> implements TaskLogInfoService {
    @Override
    public Boolean completedLogInfo(Long id, Integer status, String remark) {
        return updateChain()
                .set(TaskLogInfo::getStatus, status)
                .set(TaskLogInfo::getRemark, remark)
                .set(TaskLogInfo::getCompleteDate, new Date())
                .eq(TaskLogInfo::getId, id)
                .update();
    }

    @Override
    public Boolean completedLogInfo(Long id, String requestId, Integer status, String remark) {
        return updateChain()
                .set(TaskLogInfo::getRequestId, requestId)
                .set(TaskLogInfo::getStatus, status)
                .set(TaskLogInfo::getRemark, remark)
                .set(TaskLogInfo::getCompleteDate, new Date())
                .eq(TaskLogInfo::getId, id)
                .update();
    }

    @Override
    public Boolean setCardStatus(Long id, String cardStatus, BigDecimal cardBalance) {
        return updateChain()
                .set(TaskLogInfo::getCardStatus, cardStatus)
                .set(TaskLogInfo::getCardBalance, cardBalance)
                .eq(TaskLogInfo::getId, id)
                .update();
    }

    @Override
    public Page<TaskLogInfoVo> clientPaging(Integer pageNumber, Integer pageSize, Long userId, Role role, Long taskId, Long targetUserId, Long cardTypeId, String cardNumber, Integer status, String startDate, String endDate) {
        QueryChain<TaskLogInfo> queriedChain = queryChain();
        queriedChain.select(TASK_LOG_INFO.ALL_COLUMNS);
        queriedChain.select(USER.EMAIL.as("account"));
        queriedChain.select(CARD_TYPE.SECTION_NO.as("sectionNo"));
        queriedChain.leftJoin(USER).on(USER.ID.eq(TASK_LOG_INFO.USER_ID));
        queriedChain.leftJoin(CARD_TYPE).on(CARD_TYPE.ID.eq(TASK_LOG_INFO.CARD_TYPE_ID));
        if (RegexUtil.checkObjectIsNotNull(targetUserId)) {
            queriedChain.where(TASK_LOG.USER_ID.eq(targetUserId));
        }
        if (RegexUtil.checkObjectIsNotNull(taskId)) {
            queriedChain.where(TASK_LOG_INFO.TASK_ID.eq(taskId));
        }
        if (RegexUtil.checkObjectIsNotNull(cardTypeId)) {
            queriedChain.where(TASK_LOG_INFO.CARD_TYPE_ID.eq(cardTypeId));
        }
        if (RegexUtil.checkStringIsNotNull(cardNumber)) {
            queriedChain.where(TASK_LOG_INFO.CARD_NUMBER.like(cardNumber));
        }
        if (RegexUtil.checkObjectIsNotNull(status)) {
            queriedChain.where(TASK_LOG_INFO.STATUS.eq(status));
        }
        if (RegexUtil.checkStringIsNotNull(startDate)) {
            queriedChain.where(TASK_LOG_INFO.REQUEST_DATE.gt(DateUtil.getDayBeginDate(startDate, "yyyy-MM-dd")));
        }
        if (RegexUtil.checkStringIsNotNull(endDate)) {
            queriedChain.where(TASK_LOG_INFO.REQUEST_DATE.lt(DateUtil.getDayEndDate(endDate, "yyyy-MM-dd")));
        }

        queriedChain.orderBy(TASK_LOG_INFO.REQUEST_DATE.desc());
        return pageAs(
                Page.of(
                        pageNumber == null || pageNumber < 1 ? 1 : pageNumber,
                        pageSize == null || pageSize < 1 ? 10 : pageSize
                ),
                queriedChain,
                TaskLogInfoVo.class
        );
    }

    @Override
    public Page<BossTaskLogInfoVo> bossPaging(Integer pageNumber, Integer pageSize, Long taskId) {
        QueryChain<TaskLogInfo> queriedChain = queryChain();
        queriedChain.select(TASK_LOG_INFO.ALL_COLUMNS);
        queriedChain.select(USER.as("user").EMAIL.as("account"));
        queriedChain.select(BOSS_USER.as("dealer").EMAIL.as("dealerAccount"));
        queriedChain.select(CARD_TYPE.SECTION_NO.as("sectionNo"));
        queriedChain.select("(select email from vcc_user where id = user.parent_id limit 1) as parentAccount");
        queriedChain.leftJoin(USER.as("user")).on(USER.as("user").ID.eq(TASK_LOG_INFO.USER_ID));
        queriedChain.leftJoin(CARD_TYPE).on(CARD_TYPE.ID.eq(TASK_LOG_INFO.CARD_TYPE_ID));
        queriedChain.leftJoin(BOSS_USER.as("dealer")).on(BOSS_USER.as("dealer").ID.eq(USER.as("user").BE_LONG_TO_DEALER));
        Long bossUserId = BossUserUtil.getIdNotNull();
        if (!BossUserUtil.hasAllData()) {
            queriedChain.where(
                    BOSS_USER.as("dealer").ID.eq(bossUserId)
                            .or(BOSS_USER.as("dealer").PARENT_ID.eq(bossUserId))
            );
        }
        if (RegexUtil.checkObjectIsNotNull(taskId)) {
            queriedChain.where(TASK_LOG_INFO.TASK_ID.eq(taskId));
        }
        queriedChain.orderBy(TASK_LOG_INFO.REQUEST_DATE.desc());
        return pageAs(
                Page.of(
                        pageNumber == null || pageNumber < 1 ? 1 : pageNumber,
                        pageSize == null || pageSize < 1 ? 10 : pageSize
                ),
                queriedChain,
                BossTaskLogInfoVo.class
        );
    }

    @Override
    public Long countByTaskIdAndStatus(Long taskId, Integer status) {
        return queryChain()
                .where(TASK_LOG_INFO.TASK_ID.eq(taskId))
                .where(TASK_LOG_INFO.STATUS.eq(status, status != null))
                .count();
    }
}
